﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace PaceR.Core.Utilities
{
    public class DataGenerator
    {
        public IList<Seed> SeedData { get; set; }
        public int Size { get; set; }

        protected IList<Dictionary<string, object>> _data = new List<Dictionary<string, object>>();
        protected static Random _rand = new Random((int)Math.Round(DateTime.Now.Millisecond / Math.PI));
        protected int _currentIndex = -1;

        public DataGenerator(IEnumerable<Seed> seedData, int size = 1000)
        {
            SeedData = new List<Seed>(seedData);
            Size = size;
            Randomize();
        }

        public void Load<T>(T target)
        {
            Load(target, BindingFlags.Public | BindingFlags.Instance);
        }

        public void Load<T>(T target, BindingFlags bindingAttr)
        {
            var mockObject = Next();
            var properties = target.GetType().GetProperties(bindingAttr);
            foreach (var property in properties)
            {
                if (mockObject.Keys.Contains(property.Name) && property.CanWrite)
                {
                    property.SetValue(target, mockObject[property.Name], null);
                }
            }
            var fields = target.GetType().GetFields(bindingAttr);
            foreach (var field in fields)
            {
                if (mockObject.Keys.Contains(field.Name))
                    field.SetValue(target, mockObject[field.Name]);
            }
        }

        public Dictionary<string, object> Next()
        {
            _currentIndex++;
            if (_currentIndex >= _data.Count) _currentIndex = 0;

            return _data[_currentIndex];
        }

        protected void Randomize()
        {
            for (int i = 0; i < Size; i++)
            {
                var record = new Dictionary<string, object>();
                foreach (var seed in SeedData)
                {
                    record.Add(seed.Name, seed.GetRandomValue(_rand));
                }
                _data.Add(record);
            }
        }
    }

    public class Seed
    {
        public string Name;
        public IList<object> Data { get; protected set; }

        protected Seed(string name, IEnumerable<object> data)
        {
            Name = name;
            Data = new List<object>(data);
        }

        public static Seed Create(string name)
        {
            return Create(name, null);
        }

        public static Seed Create(string name, IEnumerable<object> data)
        {
            return new Seed(name, data);
        }

        public object GetRandomValue(Random random)
        {
            return Data[random.Next(Data.Count)];
        }
    }
}
